﻿using UnityEngine;

namespace Jinndev.UI {

    /// <summary>
    /// 根据对齐轴心设置锚点对对齐
    /// </summary>
    public class AutoAnchor : BaseUIBehaviour {

        private enum Anchor {
            TopLeft, TopCenter, TopRight,
            BottomLeft, BottomCenter, BottomRight
        }

        public float offsetY = 0;
        public float arrowOffsetY = 0;
        public RectTransform arrowUp;
        public RectTransform arrowDown;

        public void SetPivotTarget(RectTransform pivotTransform) {
            RectTransform rectTransform = GetComponent<RectTransform>();

            Vector2 pivotItemSize = pivotTransform.rect.size;
            Vector2 pivotItemPivot = pivotTransform.pivot;

            Anchor anchor = GetAnchor(pivotTransform);

            bool isTop = anchor == Anchor.TopLeft || anchor == Anchor.TopCenter || anchor == Anchor.TopRight;
            bool isLeft = anchor == Anchor.TopLeft || anchor == Anchor.BottomLeft;
            bool isRight = anchor == Anchor.TopRight || anchor == Anchor.BottomRight;

            if (anchor == Anchor.TopLeft) {
                arrowUp.anchorMin = new Vector2(0, 1);
                arrowUp.anchorMax = new Vector2(0, 1);
                rectTransform.pivot = new Vector2(0, 1);
            }
            else if (anchor == Anchor.TopCenter) {
                arrowUp.anchorMin = new Vector2(0.5f, 1);
                arrowUp.anchorMax = new Vector2(0.5f, 1);
                rectTransform.pivot = new Vector2(0.5f, 1);
            }
            else if (anchor == Anchor.TopRight) {
                arrowUp.anchorMin = new Vector2(1, 1);
                arrowUp.anchorMax = new Vector2(1, 1);
                rectTransform.pivot = new Vector2(1, 1);
            }
            else if (anchor == Anchor.BottomLeft) {
                arrowDown.anchorMin = new Vector2(0, 0);
                arrowDown.anchorMax = new Vector2(0, 0);
                rectTransform.pivot = new Vector2(0, 0);
            }
            else if (anchor == Anchor.BottomCenter) {
                arrowDown.anchorMin = new Vector2(0.5f, 0);
                arrowDown.anchorMax = new Vector2(0.5f, 0);
                rectTransform.pivot = new Vector2(0.5f, 0);
            }
            else if (anchor == Anchor.BottomRight) {
                arrowDown.anchorMin = new Vector2(1, 0);
                arrowDown.anchorMax = new Vector2(1, 0);
                rectTransform.pivot = new Vector2(1, 0);
            }

            Vector2 offset = new Vector2(0, 0);
            if (isLeft) {
                offset.x = -pivotItemSize.x * 0.5f;
            }
            else if (isRight) {
                offset.x = pivotItemSize.x * 0.5f;
            }

            if (isTop) {
                rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
                rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
                offset.y = -offsetY - arrowUp.sizeDelta.y + arrowOffsetY;
            }
            else {
                rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
                rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
                offset.y = offsetY + arrowDown.sizeDelta.y - arrowOffsetY;
            }

            // position
            rectTransform.position = pivotTransform.position;
            Vector2 anchoredPosition = rectTransform.anchoredPosition;
            Vector2 targetAnchor = GetTargetAnchor(anchor);
            anchoredPosition += pivotItemSize * (targetAnchor - pivotItemPivot) + offset;
            rectTransform.anchoredPosition = anchoredPosition;

            // arrow position
            float arrowX = 0;
            if (isLeft) {
                arrowX = pivotItemSize.x * 0.5f;
            }
            else if (isRight) {
                arrowX = -pivotItemSize.x * 0.5f;
            }
            arrowUp.gameObject.SetActive(isTop);
            arrowDown.gameObject.SetActive(!isTop);

            if (isTop) {
                arrowUp.pivot = new Vector2(0.5f, 0);
                arrowUp.anchoredPosition = new Vector2(arrowX, -arrowOffsetY);
            }
            else {
                arrowDown.pivot = new Vector2(0.5f, 1);
                arrowDown.anchoredPosition = new Vector2(arrowX, arrowOffsetY);
            }
        }

        private Vector2 GetAnchorOffset(RectTransform transform, Vector2 anchor) {
            Vector2 size = transform.rect.size;
            Vector2 pivot = transform.pivot;
            return size * (anchor - pivot);
        }

        /// <summary>
        /// 得到箭头所在的位置
        /// </summary>
        private Anchor GetAnchor(RectTransform pivotTransform) {
            // 得到屏幕内坐标，左下角(0, 0)
            Canvas canvas = pivotTransform.GetComponentInParent<Canvas>();
            Vector3 screenPoint = pivotTransform.position; //pivot的屏幕/世界坐标
            if (canvas.worldCamera != null) {
                //screenPoint = RectTransformUtility.WorldToScreenPoint(canvas.worldCamera, screenPoint);
                screenPoint = canvas.worldCamera.WorldToScreenPoint(screenPoint);
            }
            Vector2 screenSize = UIManager.Instance.ScreenUISize;
            screenPoint = screenPoint * UIManager.Instance.UIScale;

            return GetAnchorBySize(screenPoint, screenSize, pivotTransform);
            //return GetAnchorByArea(screenPoint, screenSize);
        }

        /// <summary>
        /// 根据大小
        /// </summary>
        private Anchor GetAnchorBySize(Vector2 screenPoint, Vector2 screenSize, RectTransform pivotTransform) {
            RectTransform rectTransform = GetComponent<RectTransform>();
            UIUtil.ForceLayout(rectTransform);

            Vector2 size = rectTransform.rect.size;
            Vector2 padding = new Vector2(0, arrowDown.sizeDelta.y);

            // offset计算方式: 箭头指在目标物体的正上方或正下方，而screenPoint是目标物的pivot坐标
            float midOffsetX = pivotTransform.sizeDelta.x * (0.5f - pivotTransform.pivot.x);
            float maxOffsetY = pivotTransform.sizeDelta.y * (1 - pivotTransform.pivot.y);
            //float minOffsetY = pivotTransform.sizeDelta.y * (0 - pivotTransform.pivot.y);

            bool anchorTop = screenPoint.y + maxOffsetY > screenSize.y - size.y - padding.y;
            //Debug.Log($"{screenPoint.y} + {maxOffsetY} > {screenSize.y} - {size.y} - {padding.y} = {anchorTop}");

            if (screenPoint.x + midOffsetX < size.x * 0.5f + padding.x) {
                return anchorTop ? Anchor.TopLeft : Anchor.BottomLeft;
            }
            else if (screenPoint.x + midOffsetX > screenSize.x - size.x * 0.5f - padding.x) {
                return anchorTop ? Anchor.TopRight : Anchor.BottomRight;
            }
            return anchorTop ? Anchor.TopCenter : Anchor.BottomCenter;
        }

        /// <summary>
        /// 根据区域
        /// </summary>
        private Anchor GetAnchorByArea(Vector2 screenPoint, Vector2 screenSize) {
            bool anchorTop = screenPoint.y < screenSize.y * 0.8f;

            if (screenPoint.x < screenSize.x * 0.2f) {
                return anchorTop ? Anchor.TopLeft : Anchor.BottomLeft;
            }
            else if (screenPoint.x < screenSize.x * 0.8f) {
                return anchorTop ? Anchor.TopCenter : Anchor.BottomCenter;
            }
            else {
                return anchorTop ? Anchor.TopRight : Anchor.BottomRight;
            }
        }

        private Vector2 GetTargetAnchor(Anchor anchor) {
            if (anchor == Anchor.TopLeft || anchor == Anchor.TopCenter || anchor == Anchor.TopRight) {
                return new Vector2(0.5f, 0);
            }
            else {
                return new Vector2(0.5f, 1);
            }
        }

    }

}
